#include "DrawLabel.h"


DrawLabel::DrawLabel(QWidget *parent, QRect rect):QLabel(parent),m_region(rect),m_curDrawType(DrawType::Ellipse)
{
    //设置画布大小
    this->setFixedSize(rect.size());
    m_canvas=QPixmap(rect.size()*this->screen()->devicePixelRatio());

    //将label背景这个字段不能改成全透明，因为全透明之后，QT的机制会认为这是一个无效窗口
    this->setStyleSheet("background-color:rgba(255,255,255,20);");

    //初始化画笔,颜色为黑色，宽度为
    m_curPen=QPen(QColor(0,0,0,255),2);

    setWindowFlag(Qt::WindowStaysOnTopHint);

    m_canvas.fill(QColor(200,0,0,30));
    m_canvasStack.push_back(m_canvas);

    //初始化文本类  //先隐藏
    m_textAnnotation=new TextAnnotation(this);

    //文字键入触发文本改变信号，从而触发动态调整区域信号
    connect(m_textAnnotation,&TextAnnotation::textChanged,[&](){
        m_textAnnotation->AdjustRegion();
    });
    m_textAnnotation->hide();
}

void DrawLabel::mouseMoveEvent(QMouseEvent *ev)
{
    m_endpos=ev->pos();

    if(ev->pos().x()<0){
        m_endpos.setX(0);
    }
    if(ev->pos().x()>=this->width()){
        m_endpos.setX(this->width()-1);
    }
    if(ev->pos().y()<0){
        m_endpos.setY(0);
    }
    if(ev->pos().y()>=this->height()){
        m_endpos.setY(this->height()-1);
    }
    //限制光标不超过该区域
    QCursor::setPos(mapToGlobal(m_endpos));

    //将移动获得的每个点压栈,只有随意绘制的时候压栈
    if(m_curDrawType==DrawType::CasualDraw){
        m_cursualPoints.append(m_endpos);
    }

    update();
}

void DrawLabel::mousePressEvent(QMouseEvent *ev)
{
    m_startPos=ev->pos();
    if(m_curDrawType==DrawType::CasualDraw){
        m_cursualPoints.append(m_startPos);//如果是随意绘制路线，将起点压栈
    }
    update();
}

void DrawLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    m_endpos=ev->pos();
    //记录当前的画布
    //绑定一个画笔到画布上
    QPainter painter(&m_canvas);
    painter.setPen(m_curPen);
    painter.setRenderHint(QPainter::Antialiasing,true);//抗锯齿
    painter.setRenderHint(QPainter::SmoothPixmapTransform,true);

    //再画布上绘制
    if(m_curDrawType==DrawType::None){
    }

    if(m_curDrawType==DrawType::Rect){
        //画矩形
        painter.drawRect(QRect::span(m_startPos,m_endpos));
    }

    if(m_curDrawType==DrawType::Ellipse){
        //画矩形
        painter.drawEllipse(QRect::span(m_startPos,m_endpos));
    }
    if(m_curDrawType==DrawType::Arrow){
        //画矩形
        DrawArrow(painter);
    }

    if(m_curDrawType==DrawType::CasualDraw){
        //清空文本框内容
        DrawTextFlush();
        m_textAnnotation->hide();

        painter.drawPolyline(m_cursualPoints);

        //绘制完线之后将点集数组清空
        m_cursualPoints.clear();


    }

    //当点击左键才添加文本，右键取消文本
    if(m_curDrawType==DrawType::Text && (ev->button()&Qt::LeftButton)){
        //状态为添加文本的时候
        m_textAnnotation->m_curPen.setColor(this->m_curPen.color());

        //clear之前在pixmap上绘制之前的内容,非空的情况下绘制
        if(!m_textAnnotation->toPlainText().isEmpty()){
            m_textAnnotation->DrawTextToPixmap(painter);
        }
        AddText();
    }

    if(ev->button()&Qt::RightButton&&m_curDrawType==DrawType::Text){
        DrawTextFlush();//这边已经push入栈了，在这个分支直接return
        m_textAnnotation->hide();
        return;
    }
    m_canvasStack.push_back(m_canvas);
    update();
}

void DrawLabel::paintEvent(QPaintEvent *event)
{
    QLabel::paintEvent(event);
    QPainter painter(this);

    painter.setPen(m_curPen);


#ifdef NDEBUG
    painter.setRenderHint(QPainter::Antialiasing,true);//抗锯齿
    painter.setRenderHint(QPainter::SmoothPixmapTransform,true);
#endif

    QRegion drawRegion=QRect(rect());
    painter.setClipRegion(drawRegion);

    //将画笔绑定在窗口上
    painter.drawPixmap(0,0,m_canvas);

    if(m_curDrawType==DrawType::None){
    }
    if(m_curDrawType==DrawType::Rect){
        //画矩形
        painter.drawRect(QRect::span(m_startPos,m_endpos));
    }
    if(m_curDrawType==DrawType::Ellipse){
        painter.drawEllipse(QRect::span(m_startPos,m_endpos));
    }
    if(m_curDrawType==DrawType::Arrow){
        DrawArrow(painter);
    }
    if(m_curDrawType==DrawType::CasualDraw){
        //绘制线
        painter.drawPolyline(m_cursualPoints);
    }
    if(m_curDrawType==DrawType::Text){
    }
}

/// \brief DrawLabel::ChangePen
/// \param pen，以引用的方式传入改变画板的画笔属性
/// note:每次画笔属性改变之后都会调用这个函数，更改绘画的属性和文本的颜色
void DrawLabel::ChangePen(QPen &pen)
{
    this->m_curPen=pen;

    //更改画笔属性之后自动将绘制模式改变成随意绘制
    this->m_curDrawType=DrawLabel::DrawType::CasualDraw;
    this->DrawCasual();
}

void DrawLabel::DrawRect()
{
    //改变状态
    m_curDrawType=DrawType::Rect;

    //关闭窗口
    DrawTextFlush();
    m_textAnnotation->hide();
}

void DrawLabel::DrawEllipse()
{
    m_curDrawType=DrawType::Ellipse;
    DrawTextFlush();
    m_textAnnotation->hide();
}

void DrawLabel::DrawArrow(QPainter &painter)
{
    DrawTextFlush();
    m_textAnnotation->hide();

    //从起点到终点画一条线
    painter.setPen(m_curPen);
    painter.setBrush(m_curPen.color());
    painter.save();//保存当前的绘画属性设置

    QVector2D v(m_endpos-m_startPos);
    v.normalize();
    v*=10;

    //绘制直线
    painter.drawLine(m_startPos,m_endpos-QPoint(v.x(),v.y()));

    //计算这条直线和x轴之间的夹角
    double angle=std::atan2(m_endpos.y()-m_startPos.y(),m_endpos.x()-m_startPos.x());
    double arrowSize=20;

    //计算箭头的两个点
    QPoint point_1=m_endpos-QPoint(arrowSize*std::cos(angle-M_PI/6),arrowSize*std::sin(angle-M_PI/6));
    QPoint point_2=m_endpos-QPoint(arrowSize * std::cos(angle + M_PI / 6),arrowSize * std::sin(angle + M_PI / 6));

    QPolygon arrowHead;

    arrowHead.push_back(point_1);
    arrowHead.push_back(m_endpos);
    arrowHead.push_back(point_2);

    //绘制箭头
    QPen pen(m_curPen);
    pen.setWidth(1);
    painter.setPen(pen);
    painter.drawPolygon(arrowHead);

    painter.restore();
}

void DrawLabel::DrawCasual()
{
    //鼠标划过的每一个点都记录下来,
    DrawTextFlush();
    m_textAnnotation->hide();
}

void DrawLabel::DrawText()
{
    //获取起点，以起点为起始点后创建一个Textedit窗口，此时窗口边框为实线
    qreal scalefaction=this->screen()->devicePixelRatio();

    m_textEdit=new QTextEdit(this);

    m_textEdit->setGeometry(QRect(m_startPos,QSize(100,30)));
    m_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_textEdit->setLineWrapMode(QTextEdit::WidgetWidth);//设置edit中的文字超过width自动换行
    m_textEdit->setFocus();//将这个文本编辑器设置为焦点事件
    m_textEdit->setStyleSheet("border-style:none;background-color:rgba(0,0,0,0);");//设置为无边框

    this->pixmap();


    //信号槽绑定调整宽高的函数
    connect(m_textEdit,&QTextEdit::textChanged,[&](){

        const int maxWidth = this->width()-m_startPos.x();   // 最大宽度，避免过宽,到达后自动换行
        const int maxHeight =this->height()-m_startPos.y();  // 最大高度，避免过高，到达后不允许输入

        //获取当前的文本输入框的宽和高,测量文本信息的类
        QTextDocument *doc=m_textEdit->document();
        doc->setTextWidth(maxWidth);//设置最大宽度，超出时自动换行


        qreal content_w=doc->idealWidth();
        qreal content_h=doc->size().height();

        int new_w=qMin(int (content_w+5),maxWidth);
        int new_h=qMin(int (content_h+5),maxHeight);

        m_textEdit->setFixedSize(new_w,new_h);

        m_textEdit->update();

    });

    m_textEdit->show();
}

void DrawLabel::AddText()
{
    //获取文本云关于放置的区间
    QRect textregion=QRect(m_startPos,QSize(this->size()-QSize(m_startPos.x(),m_startPos.y())));

    //设置这个窗口的布局
    m_textAnnotation->SetIdealLocation(textregion);

    //更新画笔的颜色
    m_textAnnotation->setTextColor(m_curPen.color());

    //更新画笔属性
    m_textAnnotation->update();

    //清空原来文本框中的内容
    m_textAnnotation->clear();

    //设置为焦点，方便输入
    m_textAnnotation->setFocus();

    //设置文本框状态为可用状态
    m_textAnnotation->setEnabled(true);

    //展示该窗口
    m_textAnnotation->show();
}

void DrawLabel::ComeBack()
{
    //绘制文本编辑器中内容
    DrawTextFlush();
    m_textAnnotation->hide();

    if(m_canvasStack.size()>1){

        m_canvasStack.pop_back();
        m_canvas=m_canvasStack.top();
        update();
    }
}

void DrawLabel::DrawTextFlush()
{
    QPainter painter(&m_canvas);
    painter.setPen(m_curPen);
    painter.setRenderHint(QPainter::Antialiasing,true);//抗锯齿
    painter.setRenderHint(QPainter::SmoothPixmapTransform,true);

    //clear之前在pixmap上绘制之前的内容,非空的情况下绘制
    if(!m_textAnnotation->toPlainText().isEmpty()){
        m_textAnnotation->DrawTextToPixmap(painter);
        m_canvasStack.push_back(m_canvas);
        //绘制完之后清空textAnnotation
        m_textAnnotation->clear();
        this->update();//绘制之后更新内容
    }
}

QPixmap DrawLabel::GetCanva()
{
    DrawTextFlush();
    m_textAnnotation->hide();
    return m_canvas;
}
